import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//UDP版本的回显服务器
public class EchoServer {
    //网络编程的本质——>操作网卡
    //网卡不方便直接操作，在操作系统内核中，使用“socket”这样的文件来抽象表示网卡。
    //进行网络通信，必须要先用一个socket对象
     private DatagramSocket socket=null;
     //对于服务器来说，创建socket对象的同时，要绑定一个具体的端口号
    //服务器在网络通信中处于被动的一方，如果是操作系统随机分配的端口号，那么在客户端发送请求的时候就不知道这个端口号是多少，也就无法建立连接了。
     public  EchoServer(int port) throws SocketException {
         socket=new DatagramSocket(port);
     }
     public void start() throws IOException {
         System.out.println("服务器启动");
         //服务器需要去服务很多的客户端
         while(true){
             //只要有客户端就给它提供服务
             //1.读取客户端发来的请求
             DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
             //receive传入的参数是输出型参数，要先构造这个参数
             //receive内部会针对参数对象填充数据，填充的数据来自于网卡。
             socket.receive(requestPacket);
             //此时这个DatagramPacket对象是一个特殊的对象，并不方便直接进行处理，可以把这里包含的数据拿出来，构造成一个字符串。
             String request=new String(requestPacket.getData(),0,requestPacket.getLength());
             //2.根据请求计算响应，此处是回显服务器所以直接返回请求就可以。
             String response=process(request);
             //3.将响应数据写回到客户端
             //此处构造的响应对象不能用空的字节数组来构造，应该用响应数组来构造
             DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
             socket.send(responsePacket);

             //4.打印一下，当前这次请求响应的处理中间结果
             System.out.printf("[%s:%d] req:%s;resp:%s\n",requestPacket.getAddress().toString(),
                     requestPacket.getPort(),request,response);
         }
     }

     //根据请求计算响应
    public String process(String request) {
         return request;
    }

    public static void main(String[] args) throws IOException {
        EchoServer server=new EchoServer(9090);
        server.start();
    }

}
